
/*
 * Copyright (C) Nginx, Inc.
 * Copyright (C) Valentin V. Bartenev
 * Copyright (C) Ruslan Ermilov
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_thread_pool.h>

// ngx_thread_pool_conf_t结构体用于保存线程池的配置信息
typedef struct {
    ngx_array_t               pools; // 保存所有线程池的数组
} ngx_thread_pool_conf_t;

// ngx_thread_pool_queue_t结构体用于保存线程池中任务的队列
typedef struct {
    ngx_thread_task_t        *first; // 队列中第一个任务
    ngx_thread_task_t       **last; // 队列中最后一个任务的地址
} ngx_thread_pool_queue_t;

// ngx_thread_pool_s结构体用于表示一个线程池
struct ngx_thread_pool_s {
    ngx_thread_mutex_t        mtx; // 线程互斥锁
    ngx_thread_pool_queue_t   queue; // 任务队列
    ngx_int_t                 waiting; // 等待任务的线程数
    ngx_thread_cond_t         cond; // 条件变量

    ngx_log_t                *log; // 日志对象

    ngx_str_t                 name; // 线程池名称
    ngx_uint_t                threads; // 线程个数
    ngx_int_t                 max_queue; // 最大任务队列长度

    u_char                   *file; // 文件名
    ngx_uint_t                line; // 行号
};

// 下面是一些函数的声明，具体实现可以在其他地方找到。
static ngx_int_t ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log, ngx_pool_t *pool);
static void ngx_thread_pool_destroy(ngx_thread_pool_t *tp);
static void ngx_thread_pool_exit_handler(void *data, ngx_log_t *log);

static void *ngx_thread_pool_cycle(void *data);
static void ngx_thread_pool_handler(ngx_event_t *ev);

static char *ngx_thread_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

static void *ngx_thread_pool_create_conf(ngx_cycle_t *cycle);
static char *ngx_thread_pool_init_conf(ngx_cycle_t *cycle, void *conf);

static ngx_int_t ngx_thread_pool_init_worker(ngx_cycle_t *cycle);
static void ngx_thread_pool_exit_worker(ngx_cycle_t *cycle);


//这段代码定义了几个结构体，包括`ngx_thread_pool_conf_t`用于保存线程池的配置信息，ngx_thread_pool_queue_t`用于保存线程池中任务的队列，以及`ngx_thread_pool_s`用于表示一个线程池。另外，还定义了一些函数，包括线程池的初始化、销毁和任务的处理等。
static ngx_command_t  ngx_thread_pool_commands[] = {
  // 定义线程池模块的配置指令
    { ngx_string("thread_pool"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE23,
      ngx_thread_pool,
      0,
      0,
      NULL },

      ngx_null_command
};
// 定义线程池模块的配置指令数组，其中包含了指令的名称、类型和处理函数等信息

static ngx_core_module_t  ngx_thread_pool_module_ctx = {
    ngx_string("thread_pool"),
    ngx_thread_pool_create_conf,
    ngx_thread_pool_init_conf
};
// 定义线程池模块的上下文，包括名称和配置项创建函数以及配置项初始化函数

ngx_module_t  ngx_thread_pool_module = {
    NGX_MODULE_V1,
    &ngx_thread_pool_module_ctx,           /* module context */
    ngx_thread_pool_commands,              /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    ngx_thread_pool_init_worker,           /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    ngx_thread_pool_exit_worker,           /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};
// 定义线程池模块，并指定模块的版本号、模块上下文、指令函数、模块类型以及初始化和退出函数等

static ngx_str_t  ngx_thread_pool_default = ngx_string("default");
// 定义线程池的默认名称

static ngx_uint_t               ngx_thread_pool_task_id;
static ngx_atomic_t             ngx_thread_pool_done_lock;
static ngx_thread_pool_queue_t  ngx_thread_pool_done;
// 定义一些全局变量，包括任务ID、线程池完成锁以及线程池完成任务的队列

static ngx_int_t
ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log, ngx_pool_t *pool)
{
  // 初始化线程池的函数
    int             err;
    pthread_t       tid;
    ngx_uint_t      n;
    pthread_attr_t  attr;

    if (ngx_notify == NULL) {
      // 如果事件通知机制为空，无法使用线程池
        ngx_log_error(NGX_LOG_ALERT, log, 0,
               "the configured event method cannot be used with thread pools");
        return NGX_ERROR;
    }

    ngx_thread_pool_queue_init(&tp->queue);
    // 初始化线程池的任务队列

    if (ngx_thread_mutex_create(&tp->mtx, log) != NGX_OK) {
      // 创建线程池的互斥锁
        return NGX_ERROR;
    }

    if (ngx_thread_cond_create(&tp->cond, log) != NGX_OK) {
      // 创建线程池的条件变量
        (void) ngx_thread_mutex_destroy(&tp->mtx, log);
        return NGX_ERROR;
    }

    tp->log = log;

    err = pthread_attr_init(&attr);
    if (err) {
      // 初始化线程的属性
        ngx_log_error(NGX_LOG_ALERT, log, err,
                      "pthread_attr_init() failed");
        return NGX_ERROR;
    }

    err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (err) {
      // 设置线程的分离属性
        ngx_log_error(NGX_LOG_ALERT, log, err,
                      "pthread_attr_setdetachstate() failed");
        return NGX_ERROR;
    }
    // 其他代码...

    return NGX_OK;
}
#if 0
    err = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
    if (err) {
        ngx_log_error(NGX_LOG_ALERT, log, err,
                      "pthread_attr_setstacksize() failed");
        return NGX_ERROR;
    }
#endif

// 该段代码是对线程的栈大小进行设置，使用了注释掉的 #if 0 来进行条件编译。默认情况下，将会设置栈的大小为 PTHREAD_STACK_MIN，这是一个宏定义，表示系统允许的线程栈的最小大小。

for (n = 0; n < tp->threads; n++) {
    // 使用循环创建线程
    err = pthread_create(&tid, &attr, ngx_thread_pool_cycle, tp);
    // 创建线程，并指定线程的属性、线程函数、传递给线程函数的参数
    if (err) {
        ngx_log_error(NGX_LOG_ALERT, log, err,"pthread_create() failed");
        return NGX_ERROR;
    }
}

(void) pthread_attr_destroy(&attr);
// 销毁线程属性的函数，attr为线程属性

return NGX_OK;
// 返回操作成功

static void
ngx_thread_pool_destroy(ngx_thread_pool_t *tp)
{
// 销毁线程池函数，参数为线程池指针tp
    ngx_uint_t           n;
    ngx_thread_task_t    task;
    volatile ngx_uint_t  lock;

    ngx_memzero(&task, sizeof(ngx_thread_task_t));
    // 将task结构体的内存清零

    task.handler = ngx_thread_pool_exit_handler;
    // 设置task的处理函数为ngx_thread_pool_exit_handler
    task.ctx = (void *) &lock;
    // 设置task的上下文为lock的指针

    for (n = 0; n < tp->threads; n++) {
        lock = 1;

        if (ngx_thread_task_post(tp, &task) != NGX_OK) {
            return;
        }
        // 将退出任务发送到线程池中的每个线程

        while (lock) {
            ngx_sched_yield();
        }
        // 等待任务处理完成

        task.event.active = 0;
        // 将任务设置为非激活状态
    }

    (void) ngx_thread_cond_destroy(&tp->cond, tp->log);
    // 销毁线程池的条件变量

    (void) ngx_thread_mutex_destroy(&tp->mtx, tp->log);
    // 销毁线程池的互斥锁
}

static void
ngx_thread_pool_exit_handler(void *data, ngx_log_t *log)
{
// 任务的退出处理函数，参数为数据指针和日志指针
    ngx_uint_t *lock = data;

    *lock = 0;
    // 将锁设置为0

    pthread_exit(0);
    // 结束线程
}

ngx_thread_task_t *
ngx_thread_task_alloc(ngx_pool_t *pool, size_t size)
{
// 分配线程任务的内存，参数为内存池和任务大小
    ngx_thread_task_t  *task;

    task = ngx_pcalloc(pool, sizeof(ngx_thread_task_t) + size);
    // 在内存池中分配一块内存，大小为任务结构体+任务大小
    if (task == NULL) {
        return NULL;
    }

    task->ctx = task + 1;
    // 设置任务的上下文指针为任务结构体之后的位置

    return task;
    // 返回任务指针
}

ngx_int_t
ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task)
{
// 将任务提交到线程池的任务队列中的函数，参数为线程池指针和任务指针

    if (task->event.active) {
        ngx_log_error(NGX_LOG_ALERT, tp->log, 0,
                      "task #%ui already active", task->id);
        return NGX_ERROR;
    }
    // 如果任务已经处于激活状态，则返回错误

    if (ngx_thread_mutex_lock(&tp->mtx, tp->log) != NGX_OK) {
        return NGX_ERROR;
    }
    // 加锁

    if (tp->waiting >= tp->max_queue) {
        (void) ngx_thread_mutex_unlock(&tp->mtx, tp->log);

        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
                      "thread pool \"%V\" queue overflow: %i tasks waiting",
                      &tp->name, tp->waiting);
        return NGX_ERROR;
    }
    // 如果线程池的任务队列已满，则返回错误

    task->event.active = 1;
    // 将任务设置为激活状态

    task->id = ngx_thread_pool_task_id++;
    task->next = NULL;

    if (ngx_thread_cond_signal(&tp->cond, tp->log) != NGX_OK) {
        (void) ngx_thread_mutex_unlock(&tp->mtx, tp->log);
        return NGX_ERROR;
    }
    // 通过条件变量通知线程池中的线程取出任务

    *tp->queue.last = task;
    tp->queue.last = &task->next;

    tp->waiting++;
    // 线程池中等待执行的任务数量加1

    (void) ngx_thread_mutex_unlock(&tp->mtx, tp->log);
    // 解锁

    ngx_log_debug2(NGX_LOG_DEBUG_CORE, tp->log, 0,
                   "task #%ui added to thread pool \"%V\"",
                   task->id, &tp->name);
    // 打印调试信息

    return NGX_OK;
    // 返回成功
}

墨媣(2923313175) 2023/10/30 20:26:10
逐行注释以下代码：

static void *
ngx_thread_pool_cycle(void *data)
{ // 线程池循环函数，参数为数据指针

    ngx_thread_pool_t *tp = data;
    // 将数据指针强制转换为线程池指针

    int                 err;
    sigset_t            set;
    ngx_thread_task_t  *task;

#if 0
    ngx_time_update();
#endif

    // 更新时间，此处是注释掉的代码

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, tp->log, 0,
                   "thread in pool \"%V\" started", &tp->name);
    // 打印调试信息

    sigfillset(&set);
    // 设置信号集，包含所有信号

    sigdelset(&set, SIGILL);
    sigdelset(&set, SIGFPE);
    sigdelset(&set, SIGSEGV);
    sigdelset(&set, SIGBUS);
    // 从信号集中删除一些信号，避免在处理任务时被这些信号中断

    err = pthread_sigmask(SIG_BLOCK, &set, NULL);
    if (err) {
        ngx_log_error(NGX_LOG_ALERT, tp->log, err, "pthread_sigmask() failed");
        return NULL;
    }
    // 调用pthread_sigmask函数屏蔽一些信号

    for ( ;; ) {
        // 无限循环

        if (ngx_thread_mutex_lock(&tp->mtx, tp->log) != NGX_OK) {
            return NULL;
        }
        // 上锁

        /* the number may become negative */
        tp->waiting--;
        // 等待中的任务数量减1

        while (tp->queue.first == NULL) {
            if (ngx_thread_cond_wait(&tp->cond, &tp->mtx, tp->log)
                != NGX_OK)
            {
                (void) ngx_thread_mutex_unlock(&tp->mtx, tp->log);
                return NULL;
            }
        }
        // 如果队列中没有任务，则等待条件变量，直到有任务加入队列

        task = tp->queue.first;
        tp->queue.first = task->next;
        // 将第一个任务从队列中取出

        if (tp->queue.first == NULL) {
            tp->queue.last = &tp->queue.first;
        }
        // 如果队列中没有任务了，将队列的尾指针指向队列的头指针

        if (ngx_thread_mutex_unlock(&tp->mtx, tp->log) != NGX_OK) {
            return NULL;
        }
        // 解锁

#if 0
        ngx_time_update();
#endif     // 更新时间，此处是注释掉的代码
ngx_log_debug2(NGX_LOG_DEBUG_CORE, tp->log, 0,
               "run task #%ui in thread pool \"%V\"",
               task->id, &tp->name);
// 打印调试信息，表示正在执行任务

task->handler(task->ctx, tp->log);
// 调用任务的处理函数，执行任务的实际操作

ngx_log_debug2(NGX_LOG_DEBUG_CORE, tp->log, 0,
               "complete task #%ui in thread pool \"%V\"",
               task->id, &tp->name);
// 打印调试信息，表示任务执行完成

task->next = NULL;

ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048);
// 自旋锁的方式加锁

*ngx_thread_pool_done.last = task;
ngx_thread_pool_done.last = &task->next;

ngx_memory_barrier();

ngx_unlock(&ngx_thread_pool_done_lock);
// 解锁

(void) ngx_notify(ngx_thread_pool_handler);
// 通知线程池处理函数处理任务执行完成的动作

}

static void
ngx_thread_pool_handler(ngx_event_t *ev)
{
// 线程池处理函数，参数为事件指针

    ngx_event_t        *event;
    ngx_thread_task_t  *task;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "thread pool handler");
    // 打印调试信息，表示线程池处理函数开始执行

    ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048);
    // 自旋锁的方式加锁

    task = ngx_thread_pool_done.first;
    ngx_thread_pool_done.first = NULL;
    ngx_thread_pool_done.last = &ngx_thread_pool_done.first;
    // 从全局变量中取出已完成执行的任务

    ngx_memory_barrier();
    // 内存屏障，确保对共享数据的操作不会被重排序

    ngx_unlock(&ngx_thread_pool_done_lock);
    // 解锁

    while (task) {
        // 遍历已完成执行的任务列表

        ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
                       "run completion handler for task #%ui", task->id);
        // 打印调试信息，表示正在执行任务的完成处理函数

        event = &task->event;
        task = task->next;

        event->complete = 1;
        event->active = 0;
        // 更新事件的状态，表示任务执行完成

        event->handler(event);
        // 调用事件的处理函数，处理任务完成的动作
    }
}


static void *
ngx_thread_pool_create_conf(ngx_cycle_t *cycle)//定义了一个函数 ngx_thread_pool_create_conf，该函数用于创建一个线程池配置结构体。
{
    ngx_thread_pool_conf_t  *tcf;// 分配内存空间用于线程池配置结构体

    tcf = ngx_pcalloc(cycle->pool, sizeof(ngx_thread_pool_conf_t));
    if (tcf == NULL) {
        return NULL;
    }                            //初始化线程池数组

    if (ngx_array_init(&tcf->pools, cycle->pool, 4,
                       sizeof(ngx_thread_pool_t *))
        != NGX_OK)
    {
        return NULL;
    }                       //返回线程池配置结构体

    return tcf;//返回了指向线程池配置结构体的指针 tcf
}


static char *
ngx_thread_pool_init_conf(ngx_cycle_t *cycle, void *conf)//定义一个静态函数ngx_thread_pool_init_conf，用于负责初始化线程池的配置
{
    ngx_thread_pool_conf_t *tcf = conf;// 将第二个参数（void指针）转换为线程池配置类型（ngx_thread_pool_conf_t）的指针，并将其赋值给变量tcf。  

    ngx_uint_t           i;//定义一个无符号整型变量i，它将作为循环计数器
    ngx_thread_pool_t  **tpp; // 定义一个指向线程池数组的指针tpp

    tpp = tcf->pools.elts;// 将tpp指向线程池数组的地址

    for (i = 0; i < tcf->pools.nelts; i++) {// 开始一个循环，遍历线程池数组中的每个元素

        if (tpp[i]->threads) {//判断当前线程池对象是否已经设置了线程数
            continue;//如果设置了，跳过当前循环，继续下一个循环
        }

        if (tpp[i]->name.len == ngx_thread_pool_default.len
            && ngx_strncmp(tpp[i]->name.data, ngx_thread_pool_default.data,
                           ngx_thread_pool_default.len)
               == 0)                                //判断当前线程池的名称是否与默认线程池的名称相同
        {
            tpp[i]->threads = 32; //如果相同，则设置线程数为32，最大队列大小为65536
            tpp[i]->max_queue = 65536;
            continue;//跳过当前循环，继续下一个循环
        }

        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                      "unknown thread pool \"%V\" in %s:%ui",
                      &tpp[i]->name, tpp[i]->file, tpp[i]->line);// 如果当前线程池的名称与默认线程池的名称不同，并且没有设置线程数，那么记录一个错误日志，说明未知的线程池名称

        return NGX_CONF_ERROR;//如果所有线程池都不能正确处理了，则返回NGX_CONF_ERROR，表示配置错误
    }

    return NGX_CONF_OK;//如果所有线程池都正确处理了（即每个线程池都设置了线程数或与默认线程池名称相同），则返回NGX_CONF_OK，表示配置成功
}


static char *
ngx_thread_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)//定义一个静态函数ngx_thread_pool，用于处理与线程池相关的配置
{
    ngx_str_t          *value;//定义一个指向ngx_str_t结构的指针，用于存储配置文件中的字符串参数
    ngx_uint_t          i;// 定义一个无符号整数i，用于循环计数
    ngx_thread_pool_t  *tp;//定义一个指向ngx_thread_pool_t结构的指针，用于存储线程池的信息

    value = cf->args->elts;// 将value指向的指针设置为cf->args->elts的地址，即配置参数数组的地址

    tp = ngx_thread_pool_add(cf, &value[1]);//调用ngx_thread_pool_add函数，传入配置文件上下文和线程池名称，将返回的线程池指针赋值给tp

    if (tp == NULL) {//判断ngx_thread_pool_add函数是否返回NULL
        return NGX_CONF_ERROR;// 如果ngx_thread_pool_add函数返回NULL，表示线程池添加失败，函数返回NGX_CONF_ERROR。
    }

    if (tp->threads) {//判断线程池tp的threads成员是否已经设置
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "duplicate thread pool \"%V\"", &tp->name);
        return NGX_CONF_ERROR;//如果已经设置，说明这是重复定义的线程池，返回NGX_CONF_ERROR
    }

    tp->max_queue = 65536;//默认设置线程池的最大队列大小为65536

    for (i = 2; i < cf->args->nelts; i++) {//循环遍历配置参数数组中的元素，从第三个元素开始（i=2）

        if (ngx_strncmp(value[i].data, "threads=", 8) == 0) {//判断当前参数是否以"threads="开头

            tp->threads = ngx_atoi(value[i].data + 8, value[i].len - 8);//如果是，则设置给线程池的threads成员

            if (tp->threads == (ngx_uint_t) NGX_ERROR || tp->threads == 0) {//判断当前参数是否是否符合规定或者等于0
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "invalid threads value \"%V\"", &value[i]);
                return NGX_CONF_ERROR;//如果是，则直接返回NGX_CONF_ERROR
            }

            continue;//跳出for语句的循环，进行到下一个循环
        }

        if (ngx_strncmp(value[i].data, "max_queue=", 10) == 0) {//判断当前参数是否以"max_queue="开头

            tp->max_queue = ngx_atoi(value[i].data + 10, value[i].len - 10);//如果是，则设置给线程池的max_queue成员

            if (tp->max_queue == NGX_ERROR) {//判断当前参数是否是否符合规定或者等于0
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "invalid max_queue value \"%V\"", &value[i]);
                return NGX_CONF_ERROR;//如果是，则直接返回NGX_CONF_ERROR
            }

            continue;//跳出for语句的循环，进行到下一个循环
        }
    }

    if (tp->threads == 0) {//判断线程池的线程数是否有被设置（即为0）
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"%V\" must have \"threads\" parameter",
                           &cmd->name);
        return NGX_CONF_ERROR;//如果线程池的线程数没有被设置（即为0），返回NGX_CONF_ERROR。
    }

    return NGX_CONF_OK;//如果所有配置都正确处理了，函数返回NGX
}


ngx_thread_pool_t *
ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name)//定义一个函数ngx_thread_pool_add，用于在线程池配置中添加一个新的线程池
{
    ngx_thread_pool_t       *tp, **tpp;//定义两个变量，一个是指向ngx_thread_pool_t结构的指针（tp），另一个是指向指针的指针（tpp）
    ngx_thread_pool_conf_t  *tcf;//定义了一个指向ngx_thread_pool_conf_t结构的指针（tcf）

    if (name == NULL) {//判断传入的线程池是否是NULL
        name = &ngx_thread_pool_default;//如果是NULL，则将其设置为默认的线程池名称&ngx_thread_pool_default
    }

    tp = ngx_thread_pool_get(cf->cycle, name);//调用ngx_thread_pool_get函数，从Nginx的配置循环中获取已存在的线程池。如果存在，则返回该线程池的指针，否则返回NULL

    if (tp) {//判断线程池是否存在
        return tp;// 如果线程池已经存在，则返回该线程池的指针
    }

    tp = ngx_pcalloc(cf->pool, sizeof(ngx_thread_pool_t));//使用ngx_pcalloc函数为新的线程池分配内存空间。如果分配成功，则返回线程池的指针；否则返回NULL
    if (tp == NULL) {//判断内存分配是否为失败
        return NULL; //如果内存分配失败，则返回NULL
    }

    tp->name = *name;//设置新线程池的名称为传入的名称
    tp->file = cf->conf_file->file.name.data;//设置新线程池的文件名为配置文件的名称
    tp->line = cf->conf_file->line;//设置新线程池的行号为配置文件中的行号

    tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
                                                  ngx_thread_pool_module);//从Nginx的配置上下文中获取线程池模块的配置信息，并将其赋值给tcf

    tpp = ngx_array_push(&tcf->pools);//将新线程池添加到配置的线程池数组中。如果添加成功，则返回新数组的指针；否则返回NULL
    if (tpp == NULL) {//判断是否添加失败
        return NULL;//如果添加失败，直接返回NULL
    }

    *tpp = tp;//将新分配的线程池指针赋值给数组中的新位置

    return tp;//返回新创建的线程池的指针
}//结束函数的定义


ngx_thread_pool_t *
ngx_thread_pool_get(ngx_cycle_t *cycle, ngx_str_t *name)//定义一个函数ngx_thread_pool_get，用于在线程池配置中获取一个特定名称的线程池
{
    ngx_uint_t                i;//定义一个无符号整数变量i，用于后续的循环迭代
    ngx_thread_pool_t       **tpp;//定义一个指向ngx_thread_pool_t类型的二级指针tpp，用于后续访问线程池数组
    ngx_thread_pool_conf_t   *tcf;//定义一个指向ngx_thread_pool_conf_t类型的指针tcf，用于后续访问线程池的配置信息

    tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                                  ngx_thread_pool_module);//从Nginx的配置上下文中获取线程池模块的配置信息，并将其赋值给tcf

    tpp = tcf->pools.elts;//获取tcf中存储线程池信息的数据组的首地址，并将其赋值给tpp

    for (i = 0; i < tcf->pools.nelts; i++) {//开始循环，从0到线程池数组的元素数量加1，遍历所有的线程池

        if (tpp[i]->name.len == name->len
            && ngx_strncmp(tpp[i]->name.data, name->data, name->len) == 0)//判断当前线程池的名称长度是否等于给定的名称长度和当前线程池的名称是否与给定的名称匹配
        {
            return tpp[i];//如果找到匹配的线程池，则返回该线程池的地址
        }//if语句结束
    }//for语句循环结束

    return NULL;//如果循环结束后还没有找到匹配的线程池，将返回NULL，表示没有找到
}//结束函数的定义


static ngx_int_t
ngx_thread_pool_init_worker(ngx_cycle_t *cycle)//定义一个静态函数ngx_thread_pool_init_worker，用于线程池的初始化
{                                   //函数体开始
    ngx_uint_t                i;    //定义一个无符号整数变量i,用于循环
    ngx_thread_pool_t       **tpp;  //定义一个指向ngx_thread_pool_t类型的二级指针，用于后续操作线程池
    ngx_thread_pool_conf_t   *tcf;  //定义一个指向ngx_thread_pool_conf_t类型的指针，用于访问线程池的配置信息

    if (ngx_process != NGX_PROCESS_WORKER
        && ngx_process != NGX_PROCESS_SINGLE)//判断当前进程是否为工作进程或单一进程，如果不是，则直接返回NGX_OK，表示成功
    {                               //if语句的代码块开始
        return NGX_OK;              //如果当前进程不是工作进程或单一进程，则直接返回NGX_OK
    }                               //if语句的代码块结束

    tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                                  ngx_thread_pool_module);//从Nginx的配置上下文中获取线程池的配置信息，并将其赋值给tcf指针

    if (tcf == NULL) {//判断配置信息是否获取成功，如果失败（即tcf为NULL），则直接返回NGX_OK
        return NGX_OK;//如果配置信息获取失败，则直接返回NGX_OK
    }

    ngx_thread_pool_queue_init(&ngx_thread_pool_done);//初始化一个线程池队列，命名为ngx_thread_pool_done

    tpp = tcf->pools.elts;//将tpp指向线程池配置中的线程池数组的起始位置

    for (i = 0; i < tcf->pools.nelts; i++) {//开始循环，从0到线程池数组的元素数量加1，遍历所有的线程池
        if (ngx_thread_pool_init(tpp[i], cycle->log, cycle->pool) != NGX_OK) {//对每个线程池进行初始化操作，如果初始化失败（即返回值不为NGX_OK),则直接返回NGX_ERROR
            return NGX_ERROR;//如果线程池初始化失败，则直接返回NGX_ERROR
        }//if语句循环结束
    }//for语句循环结束

    return NGX_OK;//如果线程池初始化成功，直接返回NGX_OK
}//结束函数定义


static void
ngx_thread_pool_exit_worker(ngx_cycle_t *cycle)//定义一个静态函数ngx_thread_pool_exit_worker，用于处理线程池的退出
{
    ngx_uint_t                i;//定义一个无符号整数变量i,用于循环
    ngx_thread_pool_t       **tpp;//定义一个ngx_thread_pool_t类型的二级指针tpp
    ngx_thread_pool_conf_t   *tcf;//定义一个ngx_thread_pool_conf_t类型的指针tcf

    if (ngx_process != NGX_PROCESS_WORKER
        && ngx_process != NGX_PROCESS_SINGLE)//判断当前进程是否为工作进程或单进程，如果不是，函数立即返回
    {
        return;                         //如果当前进程不是工作进程或单一进程，则直接返回
    }

    tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                                  ngx_thread_pool_module);//从Nginx的配置上下文中获取线程池的配置信息，并将其赋值给tcf

    if (tcf == NULL) //检查配置是否成功获取，如果没有获取到配置，函数立即返回
    {
        return;//如果配置获取失败，则直接返回
    }

    tpp = tcf->pools.elts;//将tpp指向线程池配置中的线程池数组的起始位置

    for (i = 0; i < tcf->pools.nelts; i++) {//开始循环，从0到线程池数组的元素数量加1，遍历所有的线程池
        ngx_thread_pool_destroy(tpp[i]);//对线程池数组中的每个函数调用ngx_thread_pool_destroy函数，已销毁对应的线程池
    }//结束for循环
}//结束函数定义
